/*建造者模式*/

#include <iostream>
#include <string>
#include <memory>

//抽象产品类
class Computer
{
    public:
        Computer() {}
        void setBoard(const std::string& board)
        {
            _board = board;
        }
        void setDisplay(const std::string& display)
        {
            _display = display;
        }
        void showParamaters()
        {
            std::string param = "Computer Paramaters:\n";
            param += "\tBoard: " + _board + "\n";
            param += "\tDisplay: " + _display + "\n";
            param += "\tOs: " + _os + "\n";
            std::cout << param << std::endl;
        }
        virtual void setOs() = 0;
    protected:
        std::string _board;
        std::string _display;
        std::string _os;
};
//具体产品类:一个具体的产品对象类
class MacBook : public Computer//继承
{
    public:
        void setOs() override
        {
            _os = "Mac OS x12";
        }
};

//抽象Builder类：创建一个产品对象所需的各个部件的抽象接口
class Builder
{
    public:
        virtual void buildBoard(const std::string& board) = 0;
        virtual void buildDisplay(const std::string& display) = 0;
        virtual void buildOs() = 0;
        virtual std::shared_ptr<Computer> build() = 0;
};
/*具体产品的具体建造者类：实现抽象接⼝，构建和组装各个部件*/
class MacBookBuilder : public Builder
{
    public:
        MacBookBuilder():_computer(new MacBook()) {}
        void buildBoard(const std::string& board)
        {
            _computer->setBoard(board);
        }
        void buildDisplay(const std::string& display)
        {
            _computer->setDisplay(display);
        }
        void buildOs()
        {
            _computer->setOs();
        }
        std::shared_ptr<Computer> build()
        {
            return _computer;
        }
    private:
        std::shared_ptr<Computer> _computer;
};

//指挥者类：提供给调用者使用，通过指挥者来构造复杂产品
//指挥者指挥建造者构造产品
class Director
{
    public:
        Director(Builder* builder):_builder(builder) {}
        void construct(const std::string& board, const std::string& display)
        {
            _builder->buildBoard(board);
            _builder->buildDisplay(display);
            _builder->buildOs();
        }
    private:
        std::shared_ptr<Builder> _builder;
};

int main()
{
    Builder* builder = new MacBookBuilder();
    std::unique_ptr<Director> director(new Director(builder));
    director->construct("华硕主板", "三星显示器");

    std::shared_ptr<Computer> computer = builder->build();
    computer->showParamaters();

    return 0;
}